package org.paradigmshift.timelapse.serializers

import net.liftweb.json.Serializer
import org.paradigmshift.timelapse.domain.Worklog
import net.liftweb.json.Formats
import net.liftweb.json.TypeInfo
import org.paradigmshift.timelapse.domain.User
import java.util.Date
import net.liftweb.json.JsonAST.JArray
import net.liftweb.json.JsonAST.JDouble
import net.liftweb.json.JsonAST.JValue
import java.text.SimpleDateFormat
import net.liftweb.json.JsonAST.JObject
import net.liftweb.json.JsonAST.JField
import net.liftweb.json.JsonAST.JString
import org.paradigmshift.timelapse.exceptions.TimeLapseException
import net.liftweb.json.JsonAST.JInt

class WorklogSerializer extends Serializer[Worklog] {
  
   private val Class = classOf[Worklog]
   private val ISO8601DateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
   
   def deserialize( implicit format:Formats ) = {
    case ( TypeInfo( Class, _ ), json) => {
      val dateFormat = new SimpleDateFormat( ISO8601DateFormat )
      val id = Option( (json \ "id").extract[String] )
      val author = Option( new User( (json \ "author" \ "name" ).extract[String], ( json \ "author" \ "displayName" ).extract[String] ) )
      val comment = ( json \ "comment" ).extract[String]
      val dateStarted = dateFormat.parse( ( json \ "started" ).extract[String] )
      val timeSpentSeconds = (json \ "timeSpentSeconds" ).extract[Int]
      
      new Worklog( id, author, comment, dateStarted, timeSpentSeconds )
    }
    case _ => throw new TimeLapseException( "Can't deserialize worklog" )
  }
  
  def serialize( implicit format:Formats ):PartialFunction[Any, JValue] = {
    case Worklog( None, None, comment, dateStarted, timeSpentSeconds ) =>
      JObject(
        serializeRequiredFields( comment, dateStarted, timeSpentSeconds )
      )
    case Worklog( Some( id ), None, comment, dateStarted, timeSpentSeconds ) =>
      JObject(
        serializeId( id ) ::
        serializeRequiredFields( comment, dateStarted, timeSpentSeconds )
      )
    case Worklog( None, Some( author ), comment, dateStarted, timeSpentSeconds ) =>
      JObject(
        serializeAuthor( author ) ::
        serializeRequiredFields( comment, dateStarted, timeSpentSeconds )
      )
    case Worklog( Some( id ), Some( author ), comment, dateStarted, timeSpentSeconds ) =>
      JObject(
        serializeId( id ) ::
        serializeAuthor( author ) ::
        serializeRequiredFields( comment, dateStarted, timeSpentSeconds )
      )
    case x => throw new TimeLapseException( "Can't serialize worklog" )
  }
  
  private def serializeRequiredFields( comment:String, started:Date, timeSpentSeconds:Int ) = {
    val dateFormat = new SimpleDateFormat( ISO8601DateFormat )
    JField( "comment", JString( comment ) ) ::
    JField( "started", JString( dateFormat.format( started ) ) ) ::
    JField( "timeSpentSeconds", JInt( timeSpentSeconds ) ) ::
    Nil
  }
  private def serializeId( id:String ) = JField( "id", JString( id ) )
  private def serializeAuthor( author:User ) = JField( "author", JObject( JField( "name", JString( author.username ) ) :: JField( "", JString( author.displayName ) ) :: Nil ) )
}